home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-16  |  7.5 KB  |  273 lines

  1. #include <exec/types.h>
  2. #include <exec/ports.h>
  3. #include <exec/memory.h>
  4. #include <devices/timer.h>
  5. #include <clib/exec_protos.h>
  6. #include <clib/alib_protos.h>
  7.  
  8. /************************************************************************
  9.  * This is a generic timer module, which exports routines to open and 
  10.  * close a UNIT_VBLANK timer, post requests to the timer and call a
  11.  * function when it returns.
  12.  * The routines defined here are reentrant.
  13.  * The only exported functions are as following:
  14.  ********
  15.  *   NAME
  16.  *     InitTimer -- initialize the timer for subsequent use.
  17.  *
  18.  *   SYNOPSIS
  19.  *     InitTimer (NumIO, TimerSignal)
  20.  *
  21.  *     void *InitTimer (int, UWORD *);
  22.  *
  23.  *   FUNCTION
  24.  *     Initialize the timer for subsequent use. This will allocate
  25.  *     all the necessary data to use the timer including a signal
  26.  *     to be used when a previously started timer expires.
  27.  *
  28.  *   INPUTS
  29.  *     NumIO - Maximum number of simultaneously active timer requests.
  30.  *     TimerSignal - A pointer to a word where the signal number is 
  31.  *                   stored which is used when a timer has expired.
  32.  *
  33.  *   RESULTS
  34.  *     Pointer to an internally used struct. Must be given in any
  35.  *     succeeding timer call. NULL otherwise.
  36.  *
  37.  ******
  38.  *   NAME
  39.  *     CloseTimer -- close a previously opened timer
  40.  *
  41.  *   SYNOPSIS
  42.  *     CloseTimer (TimerStruct)
  43.  *
  44.  *     void CloseTimer (void *);
  45.  *
  46.  *   FUNCTION
  47.  *     Closes a timer previously opened with a call to OpenTimer.
  48.  *
  49.  *   INPUTS
  50.  *     TimerStruct - The value returned by OpenTimer. This function is
  51.  *                   safe to call with a NULL argument for this.
  52.  *
  53.  *   RESULTS
  54.  *     None.
  55.  *
  56.  ******
  57.  *   NAME
  58.  *     AddTimedFunction - Add a function to be called after a certain
  59.  *                        amount of time.
  60.  *
  61.  *   SYNOPSIS
  62.  *     AddTimedFunction (TimerStruct, Secs, Micros, Function);
  63.  *
  64.  *     BOOL AddTimedFunction (void *, ULONG, ULONG, void (*) ());
  65.  *
  66.  *   FUNCTION
  67.  *     Installs a function to be called after the specified amount of
  68.  *     time. The UNIT_VBLANK timer is used for this so this will not
  69.  *     be more accurate than to 1/50 s. For periodically called functions
  70.  *     'Function' will typically include a call to AddTimedFunction.
  71.  *     'Function' is called without any parameters.
  72.  *
  73.  *   INPUTS
  74.  *     TimerStruct - The value returned by OpenTimer. This function is
  75.  *                   safe to call with a NULL argument for this. In this
  76.  *                   case AddTimedFunction does nothing.
  77.  *     Secs - Number of seconds before 'Function' will be called.
  78.  *     Micros - Together with Secs time before 'Function' will be called.
  79.  *     Function - A function without parameters to be called when the
  80.  *                timer expires.
  81.  *   
  82.  *   RESULTS
  83.  *     Returns FALSE if either TimerStruct is NULL or the number of
  84.  *     concurrently active timer request specified in OpenTimer is
  85.  *     exceeded.
  86.  *
  87.  ******
  88.  *   NAME
  89.  *     HandleTimerReturn - Perform internal timer administration when
  90.  *                         TimerSignal goes off.
  91.  *
  92.  *   SYNOPSIS
  93.  *     HandleTimerReturn (TimerStruct)
  94.  *
  95.  *     void HandleTimerReturn (void *);
  96.  *
  97.  *   FUNCTION
  98.  *     Performs internal management function for the timer whenever
  99.  *     the timer signal returned by OpenTimer arrives.
  100.  *
  101.  *   INPUTS
  102.  *     TimerStruct - The value returned by OpenTimer. This function is
  103.  *                   safe to call with a NULL argument for this. In this
  104.  *                   case AddTimedFunction does nothing.
  105.  *
  106.  *   RESULTS
  107.  *     None
  108.  *
  109.  **********************************************************************/
  110.  
  111.  
  112. struct MyTimerIO
  113.   {
  114.   struct timerequest StdTimeReq;
  115.   void (*function) (void);         /* function to be called after time has */
  116.   };                               /* elapsed */
  117.  
  118. struct TimerStruct
  119.   {
  120.   struct List TimerIOList;
  121.   struct MsgPort *TimerPort;
  122.   int NumTimerIOs;
  123.   BOOL DeviceOpen;
  124.   };
  125.  
  126. void CloseTimer (void*);
  127.  
  128. /************************************************************************/
  129.  
  130. void *InitTimer (int NumIO, UWORD *TimerSignal)
  131.  
  132. {
  133. int i;
  134. struct TimerStruct *MyTimer;
  135. struct MyTimerIO *TmpReq;
  136. struct Device *TimerDev;
  137. struct Unit   *TimerUnit;
  138.  
  139. if ((MyTimer = AllocMem (sizeof (struct TimerStruct), MEMF_ANY)) == NULL)
  140.   return (NULL);
  141.  
  142. NewList (&(MyTimer->TimerIOList));
  143.  
  144. if ((MyTimer->TimerPort = CreateMsgPort ()) == NULL)
  145.   {
  146.   CloseTimer (MyTimer);
  147.   return (NULL);
  148.   }
  149.  
  150. MyTimer->DeviceOpen = FALSE;
  151. MyTimer->NumTimerIOs = NumIO;
  152.  
  153. for (i = 0; i < NumIO; i++)
  154.   {
  155.   if ((TmpReq = CreateIORequest (MyTimer->TimerPort, 
  156.                                  sizeof (struct MyTimerIO))) == NULL)
  157.     {
  158.     CloseTimer (MyTimer);
  159.     return (NULL);
  160.     }
  161.   AddTail (&(MyTimer->TimerIOList), (struct Node*)TmpReq);
  162.   }
  163.  
  164. TmpReq = (struct MyTimerIO*) MyTimer->TimerIOList.lh_Head;
  165. if (OpenDevice ("timer.device", UNIT_VBLANK, (struct IORequest*)TmpReq, 0L) != 0)
  166.   {
  167.   CloseTimer (MyTimer);
  168.   return (NULL);
  169.   }
  170.  
  171. MyTimer->DeviceOpen = TRUE;
  172.  
  173. TimerDev  = TmpReq->StdTimeReq.tr_node.io_Device;
  174. TimerUnit = TmpReq->StdTimeReq.tr_node.io_Unit;
  175.  
  176. for (TmpReq = (struct MyTimerIO*) TmpReq->StdTimeReq.tr_node.io_Message.mn_Node.ln_Succ;
  177.      TmpReq->StdTimeReq.tr_node.io_Message.mn_Node.ln_Succ != NULL;
  178.      TmpReq = (struct MyTimerIO*) TmpReq->StdTimeReq.tr_node.io_Message.mn_Node.ln_Succ)
  179.   {
  180.   TmpReq->StdTimeReq.tr_node.io_Device = TimerDev;
  181.   TmpReq->StdTimeReq.tr_node.io_Unit   = TimerUnit;
  182.   }
  183.  
  184. *TimerSignal = MyTimer->TimerPort->mp_SigBit;
  185. return (MyTimer);
  186. }
  187.  
  188. /************************************************************************/
  189.  
  190. void CloseTimer (void *TimerStruct)
  191.  
  192. {
  193. struct TimerStruct *MyTimer;
  194. struct MyTimerIO *TmpReq;
  195. int NumOutstanding;
  196.  
  197. MyTimer = (struct TimerStruct*) TimerStruct;
  198.  
  199. if (MyTimer != NULL)
  200.   {
  201.   if (MyTimer->TimerPort != NULL)
  202.     {
  203.     NumOutstanding = MyTimer->NumTimerIOs;
  204.     while ((TmpReq = (struct MyTimerIO*)RemHead (&(MyTimer->TimerIOList))) != NULL)
  205.       {
  206.       if (--NumOutstanding == 0 && MyTimer->DeviceOpen)
  207.         CloseDevice ((struct IORequest*)TmpReq);
  208.       DeleteIORequest ((struct IORequest*)TmpReq);
  209.       }
  210.  
  211.     while (NumOutstanding > 0)
  212.       {
  213.       WaitPort (MyTimer->TimerPort);
  214.         while ((TmpReq = (struct MyTimerIO*)GetMsg (MyTimer->TimerPort)) != NULL)
  215.         {
  216.         if (--NumOutstanding == 0)
  217.           CloseDevice ((struct IORequest*)TmpReq);
  218.         DeleteIORequest ((struct IORequest*)TmpReq);
  219.         }
  220.       }
  221.     DeleteMsgPort (MyTimer->TimerPort);
  222.     }
  223.   FreeMem (MyTimer, sizeof (struct TimerStruct));
  224.   }
  225. }
  226.  
  227. /************************************************************************/
  228.  
  229. BOOL AddTimedFunction (void *TimerStruct, ULONG secs, ULONG micros, 
  230.                        void (*function) ())
  231.  
  232. {
  233. struct TimerStruct *MyTimer;
  234. struct MyTimerIO *TmpReq;
  235.  
  236. if (TimerStruct == NULL)
  237.   return (FALSE);
  238.  
  239. MyTimer = (struct TimerStruct*) TimerStruct;
  240. if ((TmpReq = (struct MyTimerIO*)RemHead (&(MyTimer->TimerIOList))) == NULL)
  241.   return (FALSE);
  242.  
  243. TmpReq->function = function;
  244. TmpReq->StdTimeReq.tr_time.tv_secs = secs;
  245. TmpReq->StdTimeReq.tr_time.tv_micro = micros;
  246. TmpReq->StdTimeReq.tr_node.io_Command = TR_ADDREQUEST;
  247. TmpReq->StdTimeReq.tr_node.io_Flags = 0;
  248.  
  249. SendIO ((struct IORequest*)TmpReq);
  250. return (TRUE);
  251. }
  252.  
  253. /************************************************************************/
  254.  
  255. void HandleTimerReturn (void *TimerStruct)
  256.  
  257. {
  258. struct TimerStruct *MyTimer;
  259. struct MyTimerIO *TmpReq;
  260. void (*tmp_func) (void);
  261.  
  262. if (TimerStruct == NULL)
  263.   return;
  264.  
  265. MyTimer = (struct TimerStruct*) TimerStruct;
  266. while ((TmpReq = (struct MyTimerIO*)GetMsg (MyTimer->TimerPort)) != NULL)
  267.   {
  268.   tmp_func = TmpReq->function;
  269.   AddTail (&(MyTimer->TimerIOList), (struct Node*)TmpReq);
  270.   (*tmp_func) ();
  271.   }
  272. }
  273.